package uebung3;

import java.io.PrintStream;

class FullArrayException extends Exception {
};

class StudDoesnExist extends Exception {
};

public class Admin {
	private BinTree<String,StudentBase> m_Studs;
	private int m_iNextFree;
	private int m_iNextMNr;
		
	Admin() {
		m_Studs = new BinTree<String,StudentBase>();
		m_iNextFree = 0;
		m_iNextMNr = 20000;
	}
	
	public StudentBase oldest() {
		return oldestYoungestHelp(0,0,true);
	}
	
	public StudentBase youngest() {
		return oldestYoungestHelp(0,0,false);
	}
	
	private StudentBase oldestYoungestHelp(int iOldest,int iIndex,boolean bOldest) {
		if (iIndex < m_iNextFree){
			if (bOldest && m_Studs.getData().get(iOldest).age() < m_Studs.getData().get(iIndex).age() ||
				!bOldest && m_Studs.getData().get(iOldest).age() > m_Studs.getData().get(iIndex).age())
				iOldest = iIndex;
			return oldestYoungestHelp(iOldest,iIndex+1,bOldest);
		} else
			return m_Studs.getData().get(iOldest);
	}
	
	public StudentBase[] bestStudents() {
		int iBestPasses = 0;
		int iNrOfBest = 0;
		for(int i = 0;i < m_iNextFree;++i) {
			int iPasses = m_Studs.getData().get(i).nrOfPassedExams();
			if (iPasses > iBestPasses) {
				iBestPasses = iPasses;
				iNrOfBest = 1;
			} else if (iPasses == iBestPasses)
				++iNrOfBest;
		}
		StudentBase[] res = new StudentBase[iNrOfBest];
		for(int i = 0,j = 0;i < m_iNextFree;++i) {
			int iPasses = m_Studs.getData().get(i).nrOfPassedExams();
			if (iPasses == iBestPasses)
				res[j++] = m_Studs.getData().get(i);
		}
		return res;
	}
	
	public StudentBase[] studsOfCourse(StudentBase.Course course) {
		int iCnt = 0;
		for(int i = 0;i < m_iNextFree;++i)
			if (m_Studs.getData().get(i).course() == course)
				++iCnt;
		StudentBase[] res = new StudentBase[iCnt];
		iCnt = 0;
		for(int i = 0;i < m_iNextFree;++i)
			if (m_Studs.getData().get(i).course() == course)
				res[iCnt++] = m_Studs.getData().get(i);
		return res;
	}

	public StudentBase[] studsWithPassedExams(int exam) {
		return studsWithPassedExams(exam,0,0);
	}

	public StudentBase[] studsWithPassedExams(int exam,int iIndex,int iNr) {
		if (iNr < m_Studs.getData().size()) {
			boolean bHasPassedExams = m_Studs.getData().get(iIndex).hasPassedExams(exam);
			StudentBase[] res = studsWithPassedExams(exam,iIndex+1,bHasPassedExams ? iNr+1 : iNr);
			if (bHasPassedExams)
				res[iNr] = m_Studs.getData().get(iIndex);
			return res;
		} else
			return new StudentBase[iNr];
	}

	public float averageAge() {
		float fRes = 0.0f;
		for(int i = 0;i < m_iNextFree;++i)
			fRes += m_Studs.getData().get(i).age();
		return fRes;
	}
	
	public void addStud(StudentBase.Course course,String name,String surname,Date birth) throws FullArrayException {
		if (m_iNextFree < m_Studs.getData().size()) {
			switch(course) {
				case INF: m_Studs.insert(name+surname, new InfStud(m_iNextMNr,name,surname,birth));break;
				case WINF: m_Studs.insert(name+surname,new WinfStud(m_iNextMNr,name,surname,birth));break;
				case PEET: m_Studs.insert(name+surname,new PeetStud(m_iNextMNr,name,surname,birth));break;
			}
			++m_iNextFree;
			++m_iNextMNr;
		} else
			throw new FullArrayException();
	}
	
	public void delStud(int iMNr) throws StudDoesnExist {
		String key="";
		for(int i=0;i<m_Studs.getData().size();++i){
			if(m_Studs.getData().get(i).mnr()==iMNr)
				key=m_Studs.getData().get(i).name()+m_Studs.getData().get(i).name();
		}
		System.out.println("Found Key "+key+" for Matrikelnr "+iMNr);
		m_Studs.remove(key);
		--m_iNextFree;
		throw new StudDoesnExist();
	}
	
	public void printHistoAge(PrintStream p) {
		final int fiYoungest = youngest().age();
		final int fiOldest = oldest().age();
		final int[] all = new int[fiOldest - fiYoungest + 1];
		for(int i = 0;i < m_iNextFree;++i) {
			++all[m_Studs.getData().get(i).age()-fiYoungest];
		}
		for(int i = 0;i < all.length;++i) {
			if (all[i] > 0)
				p.println(all[i] + " Studenten sind " + (i+fiYoungest) + " Jahre alt");
		}
	}
	
	public void printHistoExams(PrintStream p) {
		final int[] all = new int[33];
		for(int i = 0;i < m_iNextFree;++i) {
			++all[m_Studs.getData().get(i).nrOfPassedExams()];
		}
		for(int i = 0;i < all.length;++i) {
			if (all[i] > 0)
				p.println(all[i] + " Studenten haben " + i + " Examen bestanden");
		}
	}
	
	public void printAllStuds(PrintStream p) {
		for(int i = 0;i < m_iNextFree;++i)
			m_Studs.getData().get(i).print(p);
	}
	
	
}